import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Locale;
import java.util.Random; 



import pluginUtils.Circle;
import pluginUtils.CircleArrangement;
import pluginUtils.Complexe; 
import pluginUtils.DoyleCircle;
import pluginUtils.MobiusTransform;
import pluginUtils.CircleInversion;
import pluginUtils.PackCircle;
import pluginUtils.Pos3D;
import pluginUtils.Sphere;
import pluginUtils.SphereInversion;


public class GenericDrawer2carre extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000; // image size
	
	private PrintStream output;
	private double xShift=0; 
	private double zShift=0; 
	
	

	private Random generator=new Random(); // One always needs some randomness
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	private String[] palette={"Yellow","Red","Blue","Green","White","NavyBlue","Turquoise","Orange"};
	private Color[] palette1={Color.YELLOW,Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA,Color.ORANGE};
	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	 
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu; 
	}
	
	private void drawCircle(PackCircle c){
		//if(intersect(c))return; 
		
		//if(c.getRadius()<0.1) return; 
		int intX=(int)(c.getX()*acoef+ccoef);
		int intY=(int)(c.getY()*vcoef+wcoef);
		int intRx=(int)(c.getRadius()*acoef);
		int intRy=(int)(c.getRadius()*vcoef);
		int rank=((int)(c.getCouleur()*60))%6; 
	
			
			double Xs=c.getX(); 
			double Ys=c.getY(); 
			double rapp=Xs*Xs+Ys*Ys+1; 
			double u=Xs/rapp; 
			double v=Ys/rapp; 
			double w=(Xs*Xs+Ys*Ys)/rapp;
			
			double Xsr=c.getX(); 
			double Ysr=c.getY()+c.getRadius(); 
			double rappr=Xsr*Xsr+Ysr*Ysr+1; 
			double ur=Xsr/rappr; 
			double vr=Ysr/rappr; 
			double wr=(Xsr*Xsr+Ysr*Ysr)/rappr;
		
			double nrad=(u-ur)*(u-ur)+(v-vr)*(v-vr)+(w-wr)*(w-wr);
			//nrad=Math.sqrt(nrad)*1.414; 
			
			String s="sphere{<"+u+","+v+","+w+">,";
			
			
			s+=nrad; 
			s+=" texture{Texture"+rank+"} finish{Finish"+rank+"}}"; 
			output.println(s);
		
	}
		
	
	private void drawColoredCircle(PackCircle c){
		double xCenter=c.getX(); 
		double yCenter=c.getY(); 
		//if(c.getRadius()<0.001) return ; 
		
		int intX=(int)((xCenter-xShift)*acoef+ccoef);
		int intY=(int)((yCenter-zShift)*vcoef+wcoef);
		int intRx=(int)(c.getRadius()*acoef);
		int intRy=(int)(c.getRadius()*vcoef);
		
		
		primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
		
		/*
		primeIP.moveTo(intX,intY); 
		primeIP.drawString(c.getMyOrder()+"");
		*/
		
		String s="sphere{<"+xCenter+",0,"+yCenter+">,";
		s+=c.getRadius(); 
		s+=" scale 0.4*y texture{Texture"+generator.nextInt(7)+"} finish{Finish0}}"; 
		System.out.println(s); 
		output.println(s);
	
	}
	private void drawPoint(double x,double y){
		int intX=(int)(x*acoef+ccoef);
		int intY=(int)(y*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	
	private void drawTriangle(double[] X,double[] Y){
		int xint[]=new int[3]; 
		int yint[]=new int[3];
		for(int i=0;i<3;i++){
			xint[i]=(int)(X[i]*acoef+ccoef); 
			yint[i]=(int)(Y[i]*vcoef+wcoef);
		}
		primeIP.fillPolygon(new Polygon(xint,yint,3)); 
		
	}
	
	
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	
		
	
	
	
	
	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		double r2=1; //Math.sqrt(2);
		
		double limit=1.1; 
		double lmoins=-0.1;
	
		setBounds(lmoins,limit,lmoins,limit); 
		setCoefs(); 
		
		
		
		
		
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(Color.WHITE);
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(2); 
		

		setProcessor("Verifying", primeIP);
		
		/*
		double xx=lmoins; 
		double step=0.1; 
		while(xx<limit){
			drawLine(xx,lmoins,xx,limit);
			drawLine(lmoins,xx,limit,xx); 
			xx=xx+step; 
		}
		*/
		
		primeIP.setColor(Color.GREEN);
		primeIP.setLineWidth(2);
		drawLine(x0,0,x1,0);
		drawLine(0,y0,0,y1);
		
		primeIP.setColor(Color.RED);
		primeIP.setLineWidth(3);
		
		
		
		drawLine(0,0,r2,0); 
		drawLine(0,0,0,r2); 
		drawLine(0,r2,r2,0); 
		
		 int N=12; 
          
         for(int i=0;i<N+1;i++){
                 drawLine(0,(i*r2)/N,r2,(i*r2)/N); // horizontales (y en manque un en y)
                 drawLine((i*r2)/N,0,(i*r2)/N,r2); // verticales (y en manque une a la fin)
                 drawLine(0,(i*r2)/N,(i*r2)/N,0); // moitie des diagonales
                 drawLine((i*r2)/N,r2,r2,(i*r2)/N); 
                 //drawLine(r2-(i*r2)/N,r2,)
                 
         }
         
         /*
         drawTriangle(new double[]{0.4,0.5,0.4},new double[]{0.5,0.5,0.6});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.0,0.0,0.1});
         drawTriangle(new double[]{1.0,1.0,0.9},new double[]{1.0,0.9,1.0});
         drawTriangle(new double[]{0.5,0.5,0.4},new double[]{1.0,0.9,1.0});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.4,0.4,0.5});
         drawTriangle(new double[]{1.0,1.0,0.9},new double[]{0.3,0.2,0.3});
         drawTriangle(new double[]{0.7,0.8,0.7},new double[]{0.0,0.0,0.1});
         //  N=10 P=7 s=1/8
         */
         

         /*
>>>>>>> .r190
         // N=20 P=5
         //41/200
         drawTriangle(new double[]{0.55,0.55,0.5},new double[]{1.0,0.95,1.0});
         drawTriangle(new double[]{0.0,0.05,0.0},new double[]{0.0,0.0,0.05});
         drawTriangle(new double[]{1.0,1.0,0.95},new double[]{0.55,0.5,0.55});
         drawTriangle(new double[]{0.0,0.05,0.0},new double[]{0.7,0.7,0.75});
         drawTriangle(new double[]{0.7,0.75,0.7},new double[]{0.0,0.0,0.05});
         */
         
         /*
         drawTriangle(new double[]{1.0,1.0,0.9},new double[]{0.5,0.4,0.5});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.0,0.0,0.1});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.5,0.5,0.6});
         drawTriangle(new double[]{1.0,1.0,0.9},new double[]{1.0,0.9,1.0});
         drawTriangle(new double[]{0.5,0.5,0.4},new double[]{1.0,0.9,1.0});
         drawTriangle(new double[]{0.5,0.6,0.5},new double[]{0.0,0.0,0.1});
         //0.17
         //17/100
         */
         
         /*
         drawTriangle(new double[]{0.6,0.7,0.6},new double[]{0.0,0.0,0.1});
         drawTriangle(new double[]{0.6,0.6,0.5},new double[]{1.0,0.9,1.0});
         drawTriangle(new double[]{1.0,1.0,0.9},new double[]{0.6,0.5,0.6});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.6,0.6,0.7});
         drawTriangle(new double[]{0.0,0.1,0.0},new double[]{0.0,0.0,0.1});
         // N=10 P=5 0.225
         //9/40
		*/

         /*
         // N=15 P=6 s=23/150
         drawTriangle(new double[]{0.4666666666666667,0.5333333333333333,0.4666666666666667},new double[]{0.0,0.0,0.06666666666666667});
         drawTriangle(new double[]{0.0,0.06666666666666667,0.0},new double[]{0.0,0.0,0.06666666666666667});
         drawTriangle(new double[]{0.9333333333333333,1.0,0.9333333333333333},new double[]{0.4666666666666667,0.4666666666666667,0.5333333333333333});
         drawTriangle(new double[]{0.4666666666666667,0.4666666666666667,0.4},new double[]{1.0,0.9333333333333333,1.0});
         drawTriangle(new double[]{1.0,1.0,0.9333333333333333},new double[]{1.0,0.9333333333333333,1.0});
         drawTriangle(new double[]{0.0,0.06666666666666667,0.0},new double[]{0.5333333333333333,0.5333333333333333,0.6});
		*/

         
         /*
         // N=15 P=7
         
         drawTriangle(new double[]{0.0,0.06666666666666667,0.0},new double[]{0.0,0.0,0.06666666666666667});
         drawTriangle(new double[]{0.9333333333333333,1.0,0.9333333333333333},new double[]{0.2,0.2,0.26666666666666666});
         drawTriangle(new double[]{0.0,0.06666666666666667,0.0},new double[]{0.4666666666666667,0.4666666666666667,0.5333333333333333});
         drawTriangle(new double[]{1.0,1.0,0.9333333333333333},new double[]{1.0,0.9333333333333333,1.0});
         drawTriangle(new double[]{0.4,0.4666666666666667,0.4},new double[]{0.5333333333333333,0.5333333333333333,0.6});
         drawTriangle(new double[]{0.7333333333333333,0.8,0.7333333333333333},new double[]{0.0,0.0,0.06666666666666667});
         drawTriangle(new double[]{0.4666666666666667,0.5333333333333333,0.4666666666666667},new double[]{0.9333333333333333,0.9333333333333333,1.0}); 
         //0.10888888888888888
         //49/450
          */
         
         // N=12 P=8
         drawTriangle(new double[]{0.08333333333333333,0.08333333333333333,0.0},new double[]{0.75,0.6666666666666666,0.75});
         drawTriangle(new double[]{1.0,1.0,0.9166666666666666},new double[]{0.25,0.16666666666666666,0.25});
         drawTriangle(new double[]{0.0,0.08333333333333333,0.0},new double[]{0.0,0.0,0.08333333333333333});
         drawTriangle(new double[]{0.25,0.25,0.16666666666666666},new double[]{1.0,0.9166666666666666,1.0});
         drawTriangle(new double[]{0.75,0.75,0.6666666666666666},new double[]{0.08333333333333333,0.0,0.08333333333333333});
         drawTriangle(new double[]{0.25,0.3333333333333333,0.25},new double[]{0.25,0.25,0.3333333333333333});
         drawTriangle(new double[]{1.0,1.0,0.9166666666666666},new double[]{0.75,0.6666666666666666,0.75});
         drawTriangle(new double[]{0.75,0.75,0.6666666666666666},new double[]{1.0,0.9166666666666666,1.0});
         //0.09722222222222222
         //7/72

		show();
		
	}	
}




/*
 *
drawTriangle(new double[]{0.848528137423857,0.848528137423857,0.7542472332656507},new double[]{1.4142135623730951,1.319932658214889,1.4142135623730951});
drawTriangle(new double[]{1.4142135623730951,1.4142135623730951,1.319932658214889},new double[]{0.848528137423857,0.7542472332656507,0.848528137423857});
drawTriangle(new double[]{0.848528137423857,0.9428090415820634,0.848528137423857},new double[]{0.0,0.0,0.09428090415820634});
drawTriangle(new double[]{0.0,0.09428090415820634,0.0},new double[]{0.0,0.0,0.09428090415820634});
drawTriangle(new double[]{0.0,0.09428090415820634,0.0},new double[]{0.848528137423857,0.848528137423857,0.9428090415820634});
 * 
 *
 */
	